using System.Collections.Generic;
using System.Threading;

namespace ICommonLibrary.Collection {

    public class BlockingQueue<T> {

        private readonly Queue<T> _queue = new Queue<T>();
        private readonly int _maxSize;

        public BlockingQueue(int maxSize) {
            _maxSize = maxSize;
        }

        public void Enqueue(T item) {
            lock (_queue) {
                while (_queue.Count >= _maxSize) {
                    Monitor.Wait(_queue);
                }
                _queue.Enqueue(item);
                if (_queue.Count == 1) {
                    Monitor.PulseAll(_queue);
                }
            }
        }
        public T Dequeue() {
            lock (_queue) {
                while (_queue.Count == 0) {
                    Monitor.Wait(_queue);
                }
                T item = _queue.Dequeue();
                if (_queue.Count == _maxSize - 1) {
                    Monitor.PulseAll(_queue);
                }
                return item;
            }
        }

        public T TryDequeue() {
            lock (_queue) {
                while (_queue.Count == 0) {
                    return default(T);
                }
                T item = _queue.Dequeue();
                if (_queue.Count == _maxSize - 1) {
                    Monitor.PulseAll(_queue);
                }
                return item;
            }
        }


    }

}